# 函数案例

# 1. 定义一个简单的函数

def greet(name):
    """打印问候语"""
    print(f"你好，{name}!")


greet("Alice")  # 调用函数，输出: 你好，Alice!


# 2. 有返回值的函数

def add(x, y):
    """返回两个数的和"""
    return x + y


result = add(10, 20)
print(f"10 + 20 = {result}")  # 输出: 10 + 20 = 30


# 3. 默认参数值

def greet_person(name, greeting="你好"):
    """根据输入的问候语打印问候"""
    print(f"{greeting}, {name}!")


greet_person("Bob")  # 使用默认问候语，输出: 你好, Bob!
greet_person("Tom", "早安")  # 使用自定义问候语，输出: 早安, Tom!


# 4. 可变参数（*args 和 **kwargs）

def sum_all(*args):
    """计算任意数量数字的和"""
    return sum(args)


print(f"1 + 2 + 3 = {sum_all(1, 2, 3)}")  # 输出: 1 + 2 + 3 = 6
print(f"1 + 2 + 3 + 4 + 5 = {sum_all(1, 2, 3, 4, 5)}")  # 输出: 1 + 2 + 3 + 4 + 5 = 15


def print_person_info(**kwargs):
    """打印任意数量的关键字参数"""
    for key, value in kwargs.items():
        print(f"{key}: {value}")


print_person_info(name="Alice", age=25, city="北京")


# 输出:
# name: Alice
# age: 25
# city: 北京

# 5. 递归函数

def factorial(n):
    """计算阶乘"""
    if n == 0 or n == 1:
        return 1
    return n * factorial(n - 1)


print(f"5! = {factorial(5)}")  # 输出: 5! = 120

# 6. 匿名函数（lambda 函数）

# 使用 lambda 创建一个加法函数
add_lambda = lambda x, y: x + y
print(f"10 + 20 = {add_lambda(10, 20)}")  # 输出: 10 + 20 = 30

# 使用 lambda 排序一个列表（按第二个元素排序）
pairs = [(1, 2), (3, 1), (5, 4)]
pairs.sort(key=lambda pair: pair[1])
print(f"排序后的列表: {pairs}")  # 输出: 排序后的列表: [(3, 1), (1, 2), (5, 4)]

# 7. 函数的作用域

# 全局变量
x = 10


def example():
    # 局部变量
    y = 5
    print(f"局部变量 y: {y}")
    print(f"全局变量 x: {x}")


example()  # 输出: 局部变量 y: 5, 全局变量 x: 10


# 8. 闭包（函数返回函数）

def outer_function(x):
    """返回一个函数，利用 x 计算并加上 10"""

    def inner_function(y):
        return x + y + 10

    return inner_function


# 创建一个闭包
closure_function = outer_function(5)
result = closure_function(3)  # 计算 5 + 3 + 10
print(f"闭包的结果: {result}")  # 输出: 闭包的结果: 18

# 代码讲解：
# 1. 定义一个简单的函数：
#   ○ 使用 def 关键字来定义函数，函数可以有参数，并且通过 return 返回结果。greet 函数就是一个简单的打印问候语的函数。
# 2. 有返回值的函数：
#   ○ add 函数接受两个参数，并返回它们的和。返回值通过 return 语句传递给调用者。
# 3. 默认参数值：
#   ○ greet_person 函数有一个默认参数 greeting="你好"，如果调用时没有传入该参数，函数将使用默认值。
# 4. 可变参数：
#   ○ *args 允许函数接受任意数量的位置参数，sum_all 函数计算传入数字的总和。
#   ○ **kwargs 允许函数接受任意数量的关键字参数，print_person_info 函数打印所有传入的键值对。
# 5. 递归函数：
#   ○ factorial 函数是一个递归函数，用于计算给定数字的阶乘。递归函数必须有一个基本结束条件来避免无限递归。
# 6. 匿名函数（lambda 函数）：
#   ○ lambda 表达式定义了一个匿名函数。add_lambda 就是一个简单的加法运算，lambda 函数可以用来做一些临时的、一次性的计算。
# 7. 函数的作用域：
#   ○ 函数中的变量有作用域（局部和全局变量）。x 是全局变量，而 y 是局部变量。函数可以访问全局变量，但不能修改它们（除非使用 global 关键字）。
# 8. 闭包：
#   ○ outer_function 返回一个内嵌函数 inner_function，并利用 x 来生成一个闭包。闭包允许内嵌函数记住其创建时的外部环境，尤其是外部函数的局部变量。